/**
 * @author Rudy Kaplan Depena (The University of Texas at Austin)
 */
package com.utaustin.mirankerlab.ultrawrap.compiler.expressionTree.sparql;

import com.utaustin.mirankerlab.ultrawrap.compiler.exceptions.MalformedExpressionTreeException;

/** Expression Tree based on SPARQL Algebra */
public class ExpressionTree {
	
	//instance variables
	private Node root;
	
	/**
	 * Default Constructor
	 */
	public ExpressionTree(){ root = null; } //no nodes in the tree yet
	
	/**
	 * Method that assists in generating SQL by walking the tree
	 * @return sql query
	 */
	public String generateSql(){
		if(root != null){ return root.generateSql(false); }
		else{ return null; }
	}
	
	/**
	 * Insert an operand (e.g. - BGP, etc.) to help form the 
	 * appropriate algebraic expression via the expression tree
	 * @param operand
	 * @param thatLevel
	 * @throws MalformedExpressionTreeException
	 */
	public void insert(Operand operand, int thatLevel) throws MalformedExpressionTreeException{
		if(root == null){
			root = operand;
		}
		else{
			Node temp = root;
			Node tempParent = root.getParent();
			int currentLevel = temp.getLevel();
			boolean found = false;
			while(!found){
				if(currentLevel == thatLevel){
					if(temp == null){
						temp = operand;
						temp.setParent(tempParent);
						temp.setLevel(currentLevel);
						temp.getParent().setRightChild(temp);
						found = true;
					}
					else{
						throw new MalformedExpressionTreeException("shouldn't place operand in filled spot");
					}
				}
				else{
					currentLevel++;
					tempParent = temp;
					temp = temp.getRightChild();
				}
			}
		}
		while(root.getParent() != null){
			root = root.getParent();
		}
	}
	
	/**
	 * Insert an operator (e.g. - LEFT JOIN, etc.) into the expression tree to
	 * help form the SPARQL algebraic expression
	 * @param operator
	 * @param thatLevel
	 * @throws MalformedExpressionTreeException
	 */
	public void insert(Operator operator, int thatLevel) throws MalformedExpressionTreeException{
		if(root == null){
			throw new MalformedExpressionTreeException("Since Root is null, I cannot " 
					+ "guarantee that operator will have left and right operands ... " 
					+ "This situation is not currently supported "
					+ "So I am blowing up in your face ... Sorry");//TODO must fix this situation
		}
		else{
			Node temp = root;
			int currentLevel = temp.getLevel();
			boolean found = false;
			while(!found){
				if(temp.getRightChild() == null || currentLevel == thatLevel){
					operator.setParent(temp.getParent());					
					temp.setParent(operator);
					if(operator.getParent() == null){operator.setLevel(0);}
					else{operator.setLevel(operator.getParent().getLevel() + 1);}
					operator.setLeftChild(temp);
					if(operator.getParent() != null) {operator.getParent().setRightChild(operator);}
					found = true;
				}
				else{
					currentLevel++;
					temp = temp.getRightChild();
				}
			}
		}
		while(root.getParent() != null){
			root = root.getParent();
		}
	}
		
	/**
	 * Returns root of tree
	 * @return Root
	 */
	public Node getRoot(){
		return root;
	}

}
